//=======================================================================================
// PeaksAndValleys.cpp by Frank Luna (C) 2008 All Rights Reserved.
//=======================================================================================

#include "PeaksAndValleys.h"
#include "Vertex.h"
#include <vector>
#include "MyD3DMethod.h"

PeaksAndValleys::PeaksAndValleys()
: mNumRows(0), mNumCols(0), mNumVertices(0), mNumFaces(0),
  md3dDevice(0), mVB(0), mIB(0)
{
}

PeaksAndValleys::~PeaksAndValleys()
{
	ReleaseCOM(mVB);
	ReleaseCOM(mIB);
}

float PeaksAndValleys::getHeight(float x, float z)const
{
	return 0.3f*( z*sinf(0.1f*x) + x*cosf(0.1f*z) );
}

void PeaksAndValleys::init(ID3D10Device* device, DWORD m, DWORD n, float dx)
{
	md3dDevice = device;

	mNumRows  = m;
	mNumCols  = n;

	mNumVertices = m*n;
	mNumFaces    = (m-1)*(n-1)*2;

	HRESULT hr = 0;
	// Create the geometry and fill the vertex buffer. 

	std::vector<Vertex> vertices(mNumVertices);
	float halfWidth = (n-1)*dx*0.5f;
	float halfDepth = (m-1)*dx*0.5f;
	for(DWORD i = 0; i < m; ++i)
	{
		float z = halfDepth - i*dx;
		for(DWORD j = 0; j < n; ++j)
		{
			float x = -halfWidth + j*dx;

			// Graph of this function looks like a mountain range.
			float y = getHeight(x,z);

			vertices[i*n+j].pos = D3DXVECTOR3(x, y, z);

			// Color the vertex based on its height.
			if( y < -10.0f )
				vertices[i*n+j].color = BEACH_SAND;
			else if( y < 5.0f )
				vertices[i*n+j].color = LIGHT_YELLOW_GREEN;
			else if( y < 12.0f )
				vertices[i*n+j].color = DARK_YELLOW_GREEN;
			else if( y < 20.0f )
				vertices[i*n+j].color = DARKBROWN;
			else
				vertices[i*n+j].color = WHITE;
		}
	}
	mVB =	MyD3DMethod::CreatBuffer(
		sizeof(Vertex) * mNumVertices, 
		D3D10_USAGE_IMMUTABLE, 
		D3D10_BIND_VERTEX_BUFFER,
		0, 0, md3dDevice, &vertices[0]);
	if (mVB ==0)
	{
		m_bInit = false;
		return;
	}
	// Create the index buffer.  The index buffer is fixed, so we only 
	// need to create and set once.

	std::vector<DWORD> indices(mNumFaces*3); // 3 indices per face

	// Iterate over each quad and compute indices.
	int k = 0;
	for(DWORD i = 0; i < m-1; ++i)
	{
		for(DWORD j = 0; j < n-1; ++j)
		{
			indices[k]   = i*n+j;
			indices[k+1] = i*n+j+1;
			indices[k+2] = (i+1)*n+j;

			indices[k+3] = (i+1)*n+j;
			indices[k+4] = i*n+j+1;
			indices[k+5] = (i+1)*n+j+1;

			k += 6; // next quad
		}
	}

	mIB = MyD3DMethod::CreatBuffer(
		sizeof(DWORD) * mNumFaces * 3,
		D3D10_USAGE_IMMUTABLE,
		D3D10_BIND_INDEX_BUFFER,
		0, 0, md3dDevice, &indices[0]);

	if (mIB ==0)
	{
		m_bInit = false;
		return;
	
	}
	m_bInit = true;
}

void PeaksAndValleys::update(float dt)
{
}

void PeaksAndValleys::draw()
{
	if (!m_bInit)
	{
		return;
	}
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	md3dDevice->IASetVertexBuffers(0, 1, &mVB, &stride, &offset);
	md3dDevice->IASetIndexBuffer(mIB, DXGI_FORMAT_R32_UINT, 0);
    md3dDevice->DrawIndexed(mNumFaces*3, 0, 0);
}